package eclipse.lib.map;
import javax.media.opengl.*;
import javax.media.opengl.jgloo.*;
import javax.media.opengl.jgloo.jgl2d.*;
/*
 * Copyright (c) 2009, TOD Productions All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *	- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *	- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *	-Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
/**
 * The Layer class acts as a collection of GLTiles and is used to specify a single layer in a Map.
 * By default, each tile will be assigned with the blank texture, which this class assumes exists.
 * In order to use this class, you must first create the blank texture in Database.tBLANK.
 */
public final class Layer implements JGLRenderable
{
	/**
	 * The default constructor for the Layer class.
	 * This specifies the number of tiles across and the number of tiles down in the layer.
	 * @param width The number of tiles across in the layer
	 * @param height The number of tiles down in the layer
	 */
	public Layer(int width, int height)
	{
		//set the width of the layer
		setWidth(width);								
		//set the height of the layer
		setHeight(height);					
		
		//specify the size of the array 'tile'
		tile = 		new JGLTile[width][height]; 
		//specify the size of the array 'attribute'
		attribute = new TileAttribute[width][height];
		
		//loop through each tile across
		for(int w = 0; w < 20; w++)						
		{
			//loop through each tile down
			for(int h = 0; h < 15; h++)
			{			
				//create a new GLTile object for the specified tile in the array
				tile[w][h] = new JGLTile();		
				//set the default attribute
				attribute[w][h] = TileAttribute.NONE;
			}
		}
	}
	
	/**
	 * getTile returns the address to the specified tile from its x-y coordinates
	 * @param width The x-coordinate of the tile
	 * @param height The y-coordinage of the tile
	 * @return The address to the tile object located at the specified position
	 */
	public final JGLTile getTile(int width, int height)
	{
		//Just return the value of the array of GLTiles
		return tile[width][height];
	}
	
	/**
	 * setTile overwrites the address of a specified tile with a new address
	 * @param width The x-coordinate of the tile to overwrite its address
	 * @param height The y-coordinate of the tile to overwrite its address
	 * @param tile The tile address which will replace the old tile address
	 */
	public final void setTile(int width, int height, JGLTile tile)
	{
		//Just overwrite the value in the array. 
		this.tile[width][height] = tile;
	}
	
	/**
	 * The render method is supposed to mimic that of the GLObject. It tells OpenGL to draw the current object.
	 * @param gl An OpenGL instance which is used to draw the layer.
	 */
	public final void render(GL gl)
	{
		if(!isVisible())
			return;
		//loop through each tile across
		for(int x = 0; x < getWidth(); x++)
		{
			//loop through each tile down
			for(int y = 0; y < getHeight(); y++)
			{
				//check to confirm that the tile exists. Really, it should but this is just in case of an error.
				if(tile[x][y] != null)
				{
					if(tile[x][y].getTexture() != null)
					{
						//group the following draw commands
						gl.glPushMatrix();
							//move the position of the tile from the point (0,0) to one associated with its position
							gl.glTranslatef(x * 32f, y * 32f, 0f);
							//draw the tile using its 'render' method
							tile[x][y].render(gl);					
							//close the group
						gl.glPopMatrix();
					}
				}
			}
		}				
	}
	
	//Changes the width of the layer. 
	private final void setWidth(int width)
	{
		//Overwrite the class's width value with the new width value.
		this.width = width;
	}
	
	//Changes the height of the layer.
	private final void setHeight(int height)
	{
		//Overwrite the class's height value with the new height value.
		this.height = height;
	}
	
	/**
	 * getWidth gets the width of the layer
	 * @return An integer value that specifies the number of tiles across
	 */
	public final int getWidth()
	{
		//return the value representing the number of tiles across.
		return this.width;
	}
	/**
	 * getHeight gets the height of the layer
	 * @return An integer value that specifies the number of tiles down
	 */
	public final int getHeight()
	{
		//return the value representing the number of tiles down.
		return this.height;
	}	
	
	/**
	 * Sets the attribute of the tile specified by its x-y coordinates 
	 * @param x The x-coordinate of the tile
	 * @param y The y-coordinate of the tile
	 * @param attribute The Attribute that the tile will express
	 */
	public final void setAttribute(int x, int y, TileAttribute attribute)
	{
		//Set the attribute with the new attribute
		this.attribute[x][y] = attribute;
	}
	
	/**
	 * getAttribute returns the Attribute Object associated with that tile
	 * @param x	The x-coordinate of the tile
	 * @param y The y-coordinate of the tile
	 * @return The Attribute Object that carries information of the tile
	 */
	public final TileAttribute getAttribute(int x, int y)
	{		
		//Obtain the Attribute from the tile
		return attribute[x][y];
	}
	/** 
	 * Sets whether or not the layer is to be drawn
	 * @param visible True sets OpenGL to draw the layer. False sets OpenGL to skip drawing the layer
	 */
	public final void setVisible(boolean visible) 
	{
		//Set the layer as being visible
		this.visible = visible;
	}
	/** States whether or not the layer is to be drawn */
	public final boolean isVisible() 
	{
		//Return whether the layer is visible
		return visible;
	}
	private boolean visible = true;
	//Array of GLTiles arranged in a two dimension matrix
	private final JGLTile tile[][];
	//Array of Attributes arranged in a two dimension matrix
	private final TileAttribute attribute[][];
	//The number of tiles across in the layer
	private int width;
	//The number of tiles down in the layer
	private int height;
}
